package com.hdd.utils;


import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.auth.BasicCredentials;
import com.aliyuncs.auth.BasicSessionCredentials;
import com.aliyuncs.auth.STSAssumeRoleSessionCredentialsProvider;
import com.aliyuncs.ecs.model.v20140526.DescribeInstancesRequest;
import com.aliyuncs.ecs.model.v20140526.DescribeInstancesResponse;
import com.aliyuncs.profile.DefaultProfile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.rmi.ServerException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * OSS工具类(阿里云对象存储服务)
 */
@Slf4j
public final class OSSUtil {
    // 分隔符
    private static final String BAR = "/";

    // 十六进制数组
    private static final String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };


    // OSS_ENDPOINT
    public static String OSS_ENDPOINT = "http://oss-cn-hangzhou.aliyuncs.com";

    // ACCESS_ID
    public static String ACCESS_ID = "LTAI4GKSuYunsdgZEz5ymCL8";

    // ACCESS_KEY
    public static String ACCESS_KEY = "WWIoqWsmCh4GhFonIlrhdJucVyIkvF";

    // BUCKET_NAME
    public static String BUCKET_NAME = "17huadd";

    // OSS_URL
    public static String OSS_URL = "https://17huadd.oss-accelerate.aliyuncs.com";

    /**
     * 上传文件到阿里云存储
     */
    public static String uploadMultipartFileToOSS(MultipartFile mfile) throws Exception {
        // 文件名以及后缀
        String prefix = UUIDGenerator.generate();
        String suffix = mfile.getOriginalFilename().substring(mfile.getOriginalFilename().lastIndexOf("."));

        // 创建临时文件
        File temp = File.createTempFile(prefix, suffix);
        mfile.transferTo(temp);

        // md5文件 作为文件名称
        String fileName = OSSUtil.getFileMD5(temp) + suffix;

        // 初始化OSSClient
        OSSClient client = new OSSClient(OSS_ENDPOINT, ACCESS_ID, ACCESS_KEY);

        // 判断文件是否已经存在
        ObjectListing list = client.listObjects(BUCKET_NAME, fileName);
        if (list.getObjectSummaries().size() != 0) {
            temp.delete();
            return OSS_URL + BAR + fileName;
        }

        // 获取指定文件的输入流
        InputStream content=null;
        String fileUrl=null;
        try{
            content= new FileInputStream(temp);
            // 创建上传Object的Metadata
            ObjectMetadata meta = new ObjectMetadata();
            // 必须设置ContentLength
            meta.setContentLength(temp.length());
            String contentType = contentType(temp.getName().substring(temp.getName().lastIndexOf(".")));
            if (contentType != null && contentType != "") {
                meta.setContentType(contentType);
            }
            // 上传Object.
            PutObjectResult result = client.putObject(BUCKET_NAME, fileName, content, meta);
            // 判断文件的MD5值是否一致，一致则表示上传成功
            if (fileName.contains(result.getETag())) {
                log.info("****************文件上传成功，文件名：" + fileName);
            }
            fileUrl = OSS_URL + BAR + fileName;
        }finally {
            content.close();
            // 删除临时文件
            temp.delete();
        }
        return fileUrl;
    }

    /**
     * 上传文件到阿里云存储
     */
    public static String uploadMultipartFileToOSS(File file) throws Exception {

        // 后缀
//        String suffix = file.getName().substring(file.getName().lastIndexOf("."));

        // md5文件 作为文件名称
        String fileName = file.getName();
        // 初始化OSSClient
        OSSClient client = new OSSClient(OSS_ENDPOINT, ACCESS_ID, ACCESS_KEY);

        // 判断文件是否已经存在
        ObjectListing list = client.listObjects(BUCKET_NAME, fileName);
        if (list.getObjectSummaries().size() != 0) {
            file.delete();
            return OSS_URL + BAR + fileName;
        }

        // 获取指定文件的输入流
        InputStream content=null;
        String fileUrl=null;
        try {
            content= new FileInputStream(file);
            // 创建上传Object的Metadata
            ObjectMetadata meta = new ObjectMetadata();
            // 必须设置ContentLength
            meta.setContentLength(file.length());
            String contentType = contentType(fileName.substring(fileName.lastIndexOf(".")));
            if (contentType != null && contentType != "") {
                meta.setContentType(contentType);
            }
            // 上传Object.

            PutObjectResult result = client.putObject(BUCKET_NAME, fileName, content, meta);
            // 判断文件的MD5值是否一致，一致则表示上传成功
            if (fileName.contains(result.getETag())) {
                log.info("****************文件上传成功，文件名：" + fileName);
            }
            fileUrl = OSS_URL + BAR + fileName;
        }finally {
            content.close();
            // 删除临时文件
            file.delete();
        }


        return fileUrl;
    }


    /**
     * 下载图片到内存中
     *
     * @param objectName 图片地址
     * @return 图片类
     */
    public static BufferedImage downloadToImage(String objectName){
        // 创建OSSClient实例。
        OSS client = new OSSClient(OSS_ENDPOINT, ACCESS_ID, ACCESS_KEY);

        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
//        objectName = objectName.replace(OSS_URL + BAR, "");
        String s = "aliyuncs.com/";
        objectName = objectName.substring(objectName.indexOf(s) + s.length());
        OSSObject ossObject = client.getObject(BUCKET_NAME, objectName);

        // 读取文件内容。
        InputStream objectContent = ossObject.getObjectContent();
        BufferedImage read = null;
        try {
            read = ImageIO.read(objectContent);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return read;
    }

    /**
     * 下载到本地
     *
     * @param objectName 对象存储位置
     * @param pathName   保存的位置
     * @return 本地存储地址
     */
    public static String downloadToPath(String objectName, String pathName){
        // 创建OSSClient实例。
        OSS client = new OSSClient(OSS_ENDPOINT, ACCESS_ID, ACCESS_KEY);

        //objectName = objectName.replace(OSS_URL + BAR, "");
        String s = "aliyuncs.com/";
        objectName = objectName.substring(objectName.indexOf(s) + s.length());

        String path = pathName + "/" + objectName;
        // 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖，不存在则新建。
        client.getObject(new GetObjectRequest(BUCKET_NAME, objectName), new File(path));

        return path;

    }

    /**
     * 判断OSS服务文件上传时文件的contentType
     * @param FilenameExtension 文件后缀
     */
    public static String contentType(String FilenameExtension) {
        if (FilenameExtension.equals("BMP") || FilenameExtension.equals("bmp")) {
            return "image/bmp";
        }
        if (FilenameExtension.equals("GIF") || FilenameExtension.equals("gif")) {
            return "image/gif";
        }
        if (FilenameExtension.equals("JPEG") || FilenameExtension.equals("jpeg") || FilenameExtension.equals("JPG")
                || FilenameExtension.equals("jpg") || FilenameExtension.equals("PNG")
                || FilenameExtension.equals("png")) {
            return "image/jpg";
        }
        if (FilenameExtension.equals("HTML") || FilenameExtension.equals("html")) {
            return "text/html";
        }
        if (FilenameExtension.equals("TXT") || FilenameExtension.equals("txt")) {
            return "text/plain";
        }
        if (FilenameExtension.equals("VSD") || FilenameExtension.equals("vsd")) {
            return "application/vnd.visio";
        }
        if (FilenameExtension.equals("PPTX") || FilenameExtension.equals("pptx") || FilenameExtension.equals("PPT")
                || FilenameExtension.equals("ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (FilenameExtension.equals("DOCX") || FilenameExtension.equals("docx") || FilenameExtension.equals("DOC")
                || FilenameExtension.equals("doc")) {
            return "application/msword";
        }
        if (FilenameExtension.equals("XML") || FilenameExtension.equals("xml")) {
            return "text/xml";
        }
        return FilenameExtension;
    }

    /**
     * 批量删除文件接口
     */
    public static String deleteFile(String[] urls) throws Exception {
        String message = null;
        String bucketName = null;
        String fineName = null;
        int start;
        int end;
        int bucketNameEnd;
        // 初始化OSSClient
        for (int i = 0; i < urls.length; i++) {
            start = urls[i].lastIndexOf("http://");
            end = urls[i].indexOf(".oss");
            // Oss BUCKET_NAME
            bucketName = urls[i].substring(start, end);
            bucketNameEnd = bucketName.lastIndexOf("/");
            bucketName = bucketName.substring(bucketNameEnd + 1);
            // 文件名称
            fineName = urls[i].substring(urls[i].lastIndexOf(".com/"));
            fineName = fineName.substring(fineName.lastIndexOf("/") + 1);
            // 初始化OSSClient
            OSSClient client = new OSSClient(OSS_ENDPOINT, ACCESS_ID, ACCESS_KEY);
            // 判断文件是否已经存在
            ObjectListing list = client.listObjects(BUCKET_NAME, fineName);
            if (list.getObjectSummaries().size() != 0) {
                client.deleteObject(bucketName, fineName);
                message = "删除成功";
            } else {
                message = "文件不存在";
            }
            log.debug(client.getObject(bucketName, fineName) + "============");
        }
        return message;
    }

    /**
     * 获取文件的MD5值
     */
    public static String getFileMD5(File file) {
        String md5 = null;
        FileInputStream fis = null;
        ByteArrayOutputStream out = null;
        try {
            fis = new FileInputStream(file);
            out = new ByteArrayOutputStream((int) file.length());
            byte[] cache = new byte[1048576];
            for (int i = fis.read(cache); i != -1; i = fis.read(cache)) {
                out.write(cache, 0, i);
            }
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                md.update(out.toByteArray());
                md5 = byteArrayToHexString(md.digest());
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            log.error("获取文件的MD5发生异常", e);
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                // ignore
            }
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                // ignore
            }
        }
        return md5;
    }

    /**
     * 字节数组转十六进制字符串
     */
    private static String byteArrayToHexString(byte[] digest) {
        StringBuilder buffer = new StringBuilder();
        for (int i = 0; i < digest.length; i++) {
            buffer.append(byteToHexString(digest[i]));
        }
        return buffer.toString();
    }

    /**
     * 字节转十六进制字符串
     */
    private static String byteToHexString(byte b) {
        // int d1 = n/16;
        int d1 = (b & 0xf0) >> 4;
        // int d2 = n%16;
        int d2 = b & 0xf;
        return hexDigits[d1] + hexDigits[d2];
    }





    
    public static void main(String[] args) throws Exception {
//        File file=new File("E:\\img\\Chrysanthemum.jpg");
//        try {
//            String url=OSSUtil.uploadMultipartFileToOSS(file);
//            System.out.println("url:"+url);
//        } catch (Exception e) {
//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        }


//        // 创建DefaultAcsClient实例并初始化
//        DefaultProfile profile = DefaultProfile.getProfile(
//                "cn-hangzhou",               // 地域ID
//                "LTAI4GKSuYunsdgZEz5ymCL8",      // RAM账号的AccessKey ID
//                "WWIoqWsmCh4GhFonIlrhdJucVyIkvF"); // RAM账号AccessKey Secret
//        IAcsClient client = new DefaultAcsClient(profile);
//        // 创建API请求并设置参数
//        DescribeInstancesRequest request = new DescribeInstancesRequest();
//        request.setPageSize(10);
//        // 发起请求并处理应答或异常
//        DescribeInstancesResponse response;
//        try {
//            response = client.getAcsResponse(request);
//            for (DescribeInstancesResponse.Instance instance:response.getInstances()) {
//                System.out.println(instance.getPublicIpAddress());
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }


        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou");
        BasicCredentials basicCredentials = new BasicCredentials(
                "LTAI4GKSuYunsdgZEz5ymCL8",
                "WWIoqWsmCh4GhFonIlrhdJucVyIkvF"
        );
        STSAssumeRoleSessionCredentialsProvider provider = new STSAssumeRoleSessionCredentialsProvider(
                basicCredentials,
                "acs:ram::1281801172075210:role/dev",
                profile
        );
        DefaultAcsClient client = new DefaultAcsClient(profile, provider);
        DescribeInstancesRequest request = new DescribeInstancesRequest();
        try {
            DescribeInstancesResponse response = client.getAcsResponse(request);
        } catch (ClientException e) {
            System.err.println(e.toString());
        }


    }

}